<!--
 * @Author: ChunLai
 * @Date: 2023-07-25 09:48:14
 * @LastEditTime: 2025-09-08 14:16:44
 * @Description: 抄录板(上传+保存) 不校验文字
 * @FilePath: \02.bldinsure\src\views\multipages\components\TranscribeBoard.vue
-->
<template>
  <div class="signMask">
    <div class="signWrapper">
      <div class="textList" :class="{ long: nameList.length > 4 }">
        <div
          class="textItem"
          @click="current = index"
          :class="[item.finish ? 'finish' : index == current ? 'current' : '']"
          v-for="(item, index) in nameList"
          :key="index"
        >
          {{ item.text }}
        </div>
      </div>
      <div class="handCenter">
        <div class="modelBox">
          <div class="maskbot" v-if="transcribeText && current > -1">
            <span>{{ nameList[current].text }}</span>
          </div>
          <div class="maskbot2" v-if="transcribeText && current == -1">
            <span>请点击'完成'按钮,完成此次签名。</span>
          </div>
          <canvas
            id="handWriting"
            ref="handWriting"
            class="handWriting"
            disable-scroll="true"
            @touchstart="uploadScaleStart"
            @touchmove="uploadScaleMove"
            @touchend="uploadScaleEnd"
            canvas-id="handWriting"
          ></canvas>
        </div>
      </div>
      <div class="handBtn">
        <div @click="cancelDraw" class="btns cancelBtn">取消</div>
        <div @click="retDraw('1')" class="btns delBtn">重写</div>
        <div
          @click="subCanvas"
          class="btns subBtn"
          v-if="transcribeText && current === -1"
        >
          完成
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  name: "TranscribeBoard",
  computed: {
    ...mapGetters({
      applicant: "insert/applicant",
      transcribeText: "page/transcribeText",
    }),
    allFinish() {
      let flag = true;
      this.nameList.forEach((item) => {
        if (!item.img && !item.finish) {
          flag = false;
        }
      });
      return flag;
    },
  },
  data() {
    return {
      current: 0,
      canvas: "",
      context: "",
      isDraw: "",
      movePos: "",
      linWidth: "",
      linColor: "",
      trans: 0,
      outAction: null,
      nameList: [],
      trajectory: [], //轨迹集合
      errNum: 0, // 错误次数
    };
  },
  created() {
    /**防止页面滑动 */
    let that = this;
    document.body.addEventListener("touchmove", that.cancelEvent, {
      passive: false,
    });
    /**创建签名对象 */
    this.createName();
    /********禁止滑动*********/
    document.body.classList.add("van-overflow-hidden");
    /***********************/
  },
  beforeDestroy() {
    let that = this;
    document.body.removeEventListener("touchmove", that.cancelEvent, {
      passive: false,
    });
    /********禁止滑动*********/
    document.body.classList.remove("van-overflow-hidden");
    /***********************/
  },
  mounted() {
    this.$nextTick(() => {
      this.canvas = document.getElementById("handWriting");
      this.context = this.canvas.getContext("2d");
      this.isDraw = false; //定义变量控制画笔是否可用
      this.movePos; //定义变量存放初始画笔开始位置
      this.linWidth = 10;
      this.linColor = "#333";
      this.drawInit();
    });
  },
  methods: {
    /**保存当前的文字 */
    async saveCurrentTxt() {
      let img = this.canvas.toDataURL("image/png");
      this.retDraw();
      this.nameList[this.current].img = img;
      this.nameList[this.current].finish = true;
      /**显示下一个文字 */
      if (this.allFinish) {
        // 全部写完展示书写效果
        this.current = -1;
        return;
      }
      this.current++;
    },
    createName() {
      this.nameList = this.transcribeText.split("").map((item) => {
        return {
          text: item,
          finish: false,
          img: "",
        };
      });
      this.current = 0;
      this.errNum = 0;
    },
    /**初始化 */
    drawInit() {
      this.canvas.width = 350;
      this.canvas.height = 350;
      this.canvas.style.background = "transparent";
      this.context.strokeStyle = "red";
      this.context.lineWidth = 10;
      this.context.beginPath();
      // this.context.strokeRect(0, 0, 500, 500);
      //设置画笔颜色，宽度
      this.context.strokeStyle = "red";
      this.context.lineWidth = 1;
      //使线段连续，圆滑
      this.context.lineCap = "round";
      this.context.lineJoin = "round";
    },
    cancelEvent(e) {
      e.preventDefault();
    },
    /**重置 */
    retDraw(type) {
      this.context.clearRect(0, 0, this.canvas.width, 300);
      this.trajectory = [];
      this.drawInit();
      if (type && type == 1) {
        this.createName();
      }
    },
    /**取消 */
    cancelDraw() {
      this.$emit("cancelDraw");
    },
    /**点击 */
    uploadScaleStart(e) {
      if (this.current == -1) {
        this.$toast("已签署完毕！");
        return;
      }
      this.isDraw = true;
      this.movePos = this.getPos(e.touches[0].clientX, e.touches[0].clientY);
      this.drawing(e);
    },
    /**获取位置 */
    getPos(x, y) {
      var box = this.canvas.getBoundingClientRect();
      return {
        x: x - box.left,
        y: y - box.top,
      };
    },
    /**移动 */
    uploadScaleMove(e) {
      if (this.current == -1) {
        return;
      }
      this.drawing(e);
    },
    /**结束 */
    uploadScaleEnd(e) {
      if (this.current == -1) {
        return;
      }
      this.isDraw = false; // 关闭绘制开关
      this.context.stroke();
      this.dowmAction();
    },
    /**倒计时自动完成 */
    dowmAction() {
      this.outAction = setTimeout(() => {
        this.saveCurrentTxt();
      }, 1000);
    },
    /**绘制 */
    drawing(e) {
      if (this.isDraw) {
        clearTimeout(this.outAction);
        var position = this.getPos(e.touches[0].clientX, e.touches[0].clientY);
        this.trajectory = this.trajectory.concat([
          position.x.toFixed(2),
          position.y.toFixed(2),
        ]);
        this.context.strokeStyle = this.linColor;
        this.context.lineWidth = this.linWidth;
        this.context.save();
        this.context.beginPath();
        this.context.moveTo(this.movePos.x, this.movePos.y);
        this.context.lineTo(position.x, position.y);
        this.context.stroke();
        this.movePos = position;
        this.context.restore();
      }
    },
    /**判断是否已经签名 */
    isCanvasBlank(canvas) {
      return !canvas
        .getContext("2d")
        .getImageData(0, 0, canvas.width, canvas.height)
        .data.some(function (channel) {
          return channel !== 0;
        });
    },
    /**完成确认 拼合图片 */
    subCanvas() {
      var that = this,
        c = document.createElement("canvas"),
        ctx = c.getContext("2d"),
        len = this.nameList.length,
        multHe = Math.ceil(len / 22);
      c.width = 100 * (len > 22 ? 22 : len); //画布宽
      c.height = 100 * multHe; //画布高（我的每个图宽高相等，竖着是两列）
      ctx.rect(0, 0, c.width, c.height);
      c.style.background = "transparent";
      ctx.fillStyle = "transparent";
      ctx.fill();
      function drawing(n) {
        if (n < len) {
          var img = new Image();
          //img.crossOrigin = 'Anonymous'; //解决跨域
          img.src = that.nameList[n].img;
          let left = Math.floor(n / 22);
          img.onload = function () {
            ctx.drawImage(img, 100 * (n - left * 22), 100 * left, 100, 100); //10为距画布左上角的x/y坐标
            drawing(n + 1); //递归
          };
        } else {
          // 保存生成作品图片
          let img = c.toDataURL("image/png");
          // console.log(img)
          //  上传签名
          that.uploadSingImg(img);
        }
      }
      drawing(0);
    },
    uploadSingImg(img) {
      this.$store.dispatch("apis/fileAdminUpload", img).then((res) => {
        if (res.result == "1") {
          this.signDoneAndSubmit(res.url);
        } else {
          this.$toast(res.message);
        }
      });
    },
    signDoneAndSubmit(imgUrl) {
      this.$store.commit("updateLoadTxt", "签名更新中");
      let params = {
        ...this.apiComParams,
        type: "0", // 电子投保单
        imgType: "19", // 19 万能险及分红型抄录内容签字
        imgUrl: imgUrl,
        idNum: this.applicant.idNum || "",
        ocrFlag: "",
      };
      this.$store
        .dispatch("apis/comAdminApiRequest", {
          apiParams: params,
          apiName: "saveImg",
        })
        .then((res) => {
          this.cancelDraw();
          this.$emit("uploadSing");
        });
    },
  },
};
</script>

<style lang="less" scoped>
.signMask {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: 200;
  display: flex;
  align-items: flex-end;
}

.signWrapper {
  width: 100%;
  font-size: 14px;
  background-color: #fff;
  border-radius: 15px 15px 0 0;

  .handRight {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 40px;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 4px;
  }

  .handCenter {
    display: flex;
    padding: 4px 0;
    overflow: hidden;
    justify-content: center;

    .modelBox {
      position: relative;
      height: 350px;
      width: 350px;
    }

    .maskbot {
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      right: 0;
      font-size: 180px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #f1f1f1;
      background-image: url("https://wxou.mschn.cn/app_h5/insurepics/icons/signMask.png");
      background-size: cover;
      background-repeat: no-repeat;
      padding-bottom: 30px;
    }

    .maskbot2 {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 100%;
      color: #999999;
    }

    .handWriting {
      width: 100%;
      height: 350px;
      background: transparent;
      position: relative;
      z-index: 2;
    }
  }

  .handBtn {
    display: flex;
    width: 100%;
    height: 50px;
    align-items: center;
    justify-content: space-around;

    .btns {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 30%;
      height: 30px;
      border-radius: 4px;

      &.delBtn {
        background: #efefef;
      }

      &.cancelBtn {
        color: #fff;
        background: #ee0a24;
      }

      &.subBtn {
        color: #fff;
        background: #008ef6;
      }
    }
  }
}

.nameBox {
  display: flex;
  justify-content: center;
  padding: 20px 40px;

  .nameItem {
    width: 30px;
    height: 30px;
    line-height: 30px;
  }
}

.textList {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px;

  &.long {
    justify-content: flex-start;

    .textItem {
      width: 24px;
      height: 24px;
      font-size: 14px;
      margin: 2px;
      border-radius: 4px;
    }
  }

  .textItem {
    width: 60px;
    height: 60px;
    border: 1px solid #dadada;
    margin: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 36px;
    color: #999;
    border-radius: 8px;

    &.current {
      color: #008ef6;
      border-color: #008ef6;
    }

    &.finish {
      color: #65cc0c;
      border-color: #65cc0c;
    }
  }
}

.tipsTxt {
  text-align: center;
  padding-bottom: 10px;
  color: #333;
}
</style>
